const Hook = require('./Hook.js')

// 工厂类HookCodeFactory
class HookCodeFactory {
    
    args(){
        return this.options.args.join(', ')
    }

    head(){
        return `var _x = this._x;`
    }

    content(){
        let code = ''
        for(let i = 0; i<this.options.taps.length; i++){
            code += 
            ` var _fn${i} = _x[${i}]; 
              _fn${i}(${this.args()})
            `
        }
        return code
    }

    setup(instance, options){ // 先准备后续需要使用到的数据
        this.options = options // 这里的操作在源码中是通过 init 方法实现， 而我们当前是直接挂在 this 身上
        instance._x = options.taps.map(v=> v.fn) // this._x = [fn1, fn2, ...]
    }

    create(options){ // 核心就是创建一段可执行代码然后返回
        let fn //  fn = new Function("name, age", "var _x = this._x, var _fn0 = _x[0]; _fn0(name, age);")
        fn = new Function(
            this.args(),
            this.head() + this.content()
        )
        return fn
    }
}

const factory = new HookCodeFactory()

class SyncHook extends Hook {
    constructor(args){
        super(args)
    }
    compile(options){ // {taps: [{}, {}], args: [name, age] }
        factory.setup(this, options)
        return factory.create(options)
    }
}

module.exports = SyncHook